import pandas
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import random
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.p=nn.Parameter(torch.tensor([[[0.3],[0.3],[0.3]],[[0.3],[0.3],[0.3]],[[0.3],[0.3],[0.3]],[[0.3],[0.3],[0.3]]]))
    def forward(self, x):
        y = torch.tensor([0,0,0])
        for i in range(4):
            y = y +x[i].reshape(-1) * torch.t(self.p[i].reshape(-1))
            #print(x[i] * self.p[i])
        #print(y)
        y = torch.abs(y)
        y = y/torch.sum(y)
        return y
def inttoloss(x):
    if x== 0:
        return torch.tensor([1 ,0 ,0]).float()
    elif x == 1:
        return torch.tensor([0, 1 , 0]).float()
    else:
        return torch.tensor([0, 0, 1]).float()
a=pandas.read_excel("output.xlsx")
a=np.array(a.transpose())
a=torch.from_numpy(a).float()
b = torch.split(a, [4, 1], dim=1)
net=Net()
Loss=nn.CrossEntropyLoss()
opt=torch.optim.Adam(net.parameters(),lr=0.000001)
try:
    for j in range(5):
        loss=0
        arci=0
        for h in range(10):
            index = random.randint(0, 390)
            inputs = b[0][index]
            realinput=[]
            for q in inputs:
                realinput.append(inttoloss(q))
            #print(realinput)
            realinput = torch.stack(realinput)
            #print(realinput)
            out = net(realinput)
            if int(torch.argmax(out)) == b[1][index]:
                arci = arci + 1
            loss = loss + Loss(out, inttoloss(b[1][index]))


            #print(out)
            # print(inputs[1].cuda(), out[i])

            #print(int(torch.argmax(out)),b[1][index])
        opt.zero_grad()
        loss = loss/10
        arci = arci / 10
        loss.backward()
        '''
        for name, param in net.named_parameters():
            if param.requires_grad:
                print(name, param.grad)
        '''



        opt.step()
        #print(loss,arci)
        #print(out,b[1][index])
        #print(net.p)
    arci = 0
    for index in range(391,584):
        inputs = b[0][index]
        realinput = []
        for q in inputs:
            realinput.append(inttoloss(q))
        # print(realinput)
        realinput = torch.stack(realinput)
        # print(realinput)
        out = net(realinput)
        if int(torch.argmax(out)) == b[1][index]:
            arci = arci + 1

        # print(out)
        # print(inputs[1].cuda(), out[i])

        print(int(torch.argmax(out)), b[1][index])
    arci = arci / (584 - 391)
    print(arci)

except KeyboardInterrupt:
    pass